#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

#include "common.cpp"

struct channel
{
    channel(int wfd, pid_t pid, const string &name)
        : _wfd(wfd), _pid(pid), _process_name(name)
    {
    }
    void Close()
    {
        close(_wfd);
    }
    int _wfd;
    pid_t _pid;
    string _process_name;
};

class ProcessPool
{
public:
    ProcessPool(int number)
        : _process_number(number)
    {
    }

    //创建进程
    void Create()
    {
        //在子进程中关闭父进程打开的写端
        vector<int> tmp;
        for (int i = 0; i < _process_number; i++)
        {
            int pipeArr[2] = {0};
            int n = pipe(pipeArr);
            //为了方便，这里就不作检查了
            // if (n < 0)
            // {
            //     cout << "pipe create error : " << strerror(errno) << endl;
            // }
            pid_t id = fork();
            if (id == 0)
            {
                if(tmp.size())
                {
                    for(auto e : tmp)
                        close(e);
                }
                // child r
                // 关闭写端
                close(pipeArr[1]);
                // 把读端重定向到0
                dup2(pipeArr[0], 0);
                // TODO...
                work(pipeArr[0]);
                exit(0);
            }
            // father w
            // 关闭读端
            close(pipeArr[0]);
            string cname = "channel-" + to_string(i);
            _process_pool.emplace_back(pipeArr[1], id, cname);
            tmp.push_back(pipeArr[1]);
        }
    }

    //轮询方式访问每一个进程
    int NextChannel()
    {
        static int c = 0;
        int ret = c++;
        c %= _process_number;
        return ret;
    }

    void SendTasks(int count)
    {
        if(count <= 0)
            return;
        while(count--)
        {
            //基于轮询的方式找出一个进程池
            int idx = NextChannel();

            //需要执行的任务编号
            int task_id = GetTaskID();

            //将编号发送给指定进程
            write(_process_pool[idx]._wfd, &task_id, sizeof task_id);
            sleep(1);
            cout << "father send a task to child, count:" << count << endl;
        }
    }

    void Kill()
    {
        for (auto& chan : _process_pool)
        {
            chan.Close();
            pid_t pid = chan._pid;
            pid_t rid = waitpid(pid, nullptr, 0);
            if(rid == pid)
            {
                cout << "wait process success" << endl;
            }
        }
    }

private:
    vector<channel> _process_pool;
    size_t _process_number;
};

void Useage(const string &s)
{
    cout << "Use: " << s << " process_numbers(n >= 1)" << endl;
}

int main(int argc, char *argv[])
{
    srand((unsigned int)time(NULL));
    if (argc != 2)
    {
        Useage(argv[0]);
        return 1;
    }
    int process_number = stoi(argv[1]);
    if (process_number <= 0)
    {
        Useage(argv[0]);
        return 1;
    }

    // proess_pool_pointer
    ProcessPool *ppptr = new ProcessPool(process_number);
    ppptr->Create();

    //发送任务
    ppptr->SendTasks(10);

    ppptr->Kill();
    delete ppptr;
    ppptr = nullptr;
    return 0;
}